package org.thss.petri.gef.ui;

import java.io.IOException;
import java.util.EventObject;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.parts.GraphicalEditorWithPalette;
import org.eclipse.gef.ui.properties.UndoablePropertySheetEntry;
import org.eclipse.gef.ui.properties.UndoablePropertySheetPage;
import org.eclipse.jface.action.IAction;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.IPropertySourceProvider;
import org.eclipse.ui.views.properties.PropertySheetPage;
import org.thss.petri.gef.actions.FirePetriNetAction;
import org.thss.petri.gef.actions.FireTransitionAction;
import org.thss.petri.gef.editparts.GraphicalEditPartFactory;
import org.thss.petri.model.PetriFactory;
import org.thss.petri.model.PetriNet;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;

/**
 * PetriNet Editor
 * @author chenhz
 *
 */
public class PetriNetEditor extends GraphicalEditorWithPalette {

	public static final String ID = "org.thss.petri.gef.ui.PetriNetEditor";
	
	private Resource resource = null;
	private PetriNet net = null;
	
	private PropertySheetPage propertyPage;
	

	public PetriNetEditor() {
		setEditDomain(new DefaultEditDomain(this));
	}
	
	@Override
	protected PaletteRoot getPaletteRoot() {
		return PetriNetPaletteFactory.createPalette();
	}
	
	@Override
	protected void configureGraphicalViewer() {
		super.configureGraphicalViewer();
		getGraphicalViewer().setEditPartFactory(new GraphicalEditPartFactory());
	}

	@Override
	protected void initializeGraphicalViewer() {
		GraphicalViewer viewer = getGraphicalViewer();
		viewer.setContents(net);
	}

	@Override
	public void doSave(IProgressMonitor monitor) {		
		if (resource == null) {
			return;
		}
		try {
			resource.save(null);
			getCommandStack().markSaveLocation();
		} catch (IOException e) {
			e.printStackTrace();
			resource = null;
		}
	}
	
	@Override
	public void commandStackChanged(EventObject event) {
        firePropertyChange(PROP_DIRTY);
        super.commandStackChanged(event);
    }
	
	@Override
	protected void createActions() {
		// TODO Auto-generated method stub
		super.createActions();
		
		ActionRegistry registry = getActionRegistry();
		IAction action = new FireTransitionAction((IWorkbenchPart)this);
		registry.registerAction(action);
		getSelectionActions().add(action.getId());
		
		action = new FirePetriNetAction(this);
		registry.registerAction(action);
		getPropertyActions().add(action.getId());
		
	}
	

	@Override
	public void init(IEditorSite site, IEditorInput input) throws PartInitException {
	    super.init(site, input);
	    
	    ResourceSet resourceSet = new ResourceSetImpl();
		resourceSet.getPackageRegistry().put("", PetriFactory.eINSTANCE);
		resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap()
				.put(".pnl", new XMIResourceFactoryImpl());
		
		IFileEditorInput fileInput = (IFileEditorInput) input;
		IFile file = fileInput.getFile();
		resource = resourceSet.createResource(URI.createURI(file.getLocationURI().toString()));

		try {
			resource.load(null);
			net = (PetriNet) resource.getContents().get(0);
		} catch (IOException e) {
			net = PetriFactory.eINSTANCE.createPetriNet();
			resource.getContents().add(net);
		} catch (IndexOutOfBoundsException e) {
			net = PetriFactory.eINSTANCE.createPetriNet();
			resource.getContents().add(net);
		}
	}
	
	
	@Override
	public Object getAdapter(Class type) {
		// TODO Auto-generated method stub
		if(type.equals(IPropertySheetPage.class)) {
			if(propertyPage == null){
				propertyPage = (UndoablePropertySheetPage) super.getAdapter(type);
				IPropertySourceProvider sourceProvider = new  PetriNetPropertySourceProvider();
				UndoablePropertySheetEntry root = new UndoablePropertySheetEntry(getCommandStack());
				root.setPropertySourceProvider(sourceProvider);
				propertyPage.setRootEntry(root);
			}
			return propertyPage;
		}
		
		return super.getAdapter(type);
	}
	

	public EditPart getPetriNetEditPart(){
		try{
			EditPart rootEditPart = this.getGraphicalViewer().getRootEditPart();
			return  (EditPart)rootEditPart.getChildren().get(0);
			
		}
		catch(Exception e){
			return null;
		}
	}
}
